package web.Annotation;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.util.internal.StringUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import web.bo.AddFrequencyBo;
import web.entity.Security_UserDetail;
import web.entity.UserDo;
import web.entity.admin.log.SearchDo;
import web.entity.admin.log.ViewDownloadDo;
import web.mapper.LogMysqlMapper;
import web.service.IndexService;
import web.service.LogService;
import web.staticParam.LogtypeStaticParam;
import web.utils.RandomUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Aspect
@Component
public class LogAspect {
    @Autowired
    private IndexService indexService;

    @Autowired
    LogMysqlMapper logMysqlMapper;
    @Autowired
    LogService logService;
    @Pointcut("@annotation(web.Annotation.LogAnnotation)")

    /*定义切点(名字随意)*/
    public void myCheckPoint() {

    }

    /*切点前执行 void*/
    @Before("myCheckPoint()")
    public void beforePoint(JoinPoint joinPoint) {
//        System.out.println("beforePoint");
    }

    /*切点后执行*/
    @After("myCheckPoint()")
    public void afterPoint(JoinPoint joinPoint) throws IOException {
//        System.out.println(joinPoint);
//        System.out.println("afterPoint");
//        Object[] args = joinPoint.getArgs();
        insertLog(joinPoint);
    }

    @Around("myCheckPoint()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("around");
        return pjp.proceed();
    }

    private void insertLog(JoinPoint pjp) throws IOException {
        MethodSignature signature = (MethodSignature) pjp.getSignature();//从切面织入点处，通过反射机制获取织入点处的方法
        Method method = signature.getMethod();//获取切入点所在的方法
        LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);//获取注解内容
        String arg = logAnnotation.value();
        HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();


        if (LogtypeStaticParam.LOGIN.equals(arg)) {
//            loginLog(req);
        } else if (LogtypeStaticParam.VIEW.equals(arg)) {
            viewLog(req);
        } else if (LogtypeStaticParam.DOWNLOAD.equals(arg)) {
            downloadLog(req);
        } else if (LogtypeStaticParam.SEARCH.equals(arg)) {
            searchLog(req);
        }

    }

    private void viewLog(HttpServletRequest req) {
        /*获取登录信息*/
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Security_UserDetail detail = (Security_UserDetail) authentication.getPrincipal();
        UserDo usr = detail.getUserDo();
        /*浏览日志实体类*/
        ViewDownloadDo viewDownloadDo = new ViewDownloadDo();
        viewDownloadDo.setUser_id(usr.getAccount());
        viewDownloadDo.setUser_name(usr.getUser_name());
        viewDownloadDo.setIp(req.getRemoteAddr());
        viewDownloadDo.setResource_id(req.getParameter("resource_id"));
        viewDownloadDo.setResource_code(req.getParameter("resource_code"));
        viewDownloadDo.setResource_name(req.getParameter("resource_name"));
        viewDownloadDo.setResource_title(req.getParameter("resource_title"));
        viewDownloadDo.setUrl(req.getParameter("url"));
        viewDownloadDo.setCreate_time(RandomUtils.nowStr(""));
        /*插入浏览日志*/
        AddFrequencyBo ee = new AddFrequencyBo();
        ee.setId(viewDownloadDo.getResource_id());
        ee.setTABLENAME(viewDownloadDo.getResource_code());
        indexService.BrowseFrequency(ee);
        viewDownloadDo.setHyfl_code(logService.getHyfl_codeByKnowledge(req.getParameter("resource_code"),req.getParameter("resource_id")));
        logMysqlMapper.insertViewLog(viewDownloadDo);
    }

    private void downloadLog(HttpServletRequest req) {
        /*获取登录信息*/
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Security_UserDetail detail = (Security_UserDetail) authentication.getPrincipal();
        UserDo usr = detail.getUserDo();
        /*浏览日志实体类*/
        ViewDownloadDo viewDownloadDo = new ViewDownloadDo();
        viewDownloadDo.setUser_id(usr.getAccount());
        viewDownloadDo.setUser_name(usr.getUser_name());
        viewDownloadDo.setIp(req.getRemoteAddr());
        //资源id（无id为文件名）
        String resource_id = "";
        //表名
        String resource_code = "";
        //来源
        String resource_name = "";
        //标题
        String resource_title = "";


        String resourceId = req.getParameter("resource_id");
        String resourceCode = req.getParameter("resource_code");
        String resourceName = req.getParameter("resource_name");
        String resourceTitle = req.getParameter("resource_title");
        //数据ID
        resource_id=resourceId;
        //来源
        resource_name=resourceName;

        //数据库表名
        if (StringUtils.hasLength(resourceCode)) {
            resource_code = resourceCode;
        }else{
            resource_code = req.getParameter("tableName");
        }

        //文件名
        if (StringUtils.hasLength(resourceTitle)) {
            resource_title = resourceTitle;
        }else{
            resource_title = req.getParameter("fileName");
        }


        viewDownloadDo.setResource_id(resource_title);
        viewDownloadDo.setResource_code(resource_code);
        viewDownloadDo.setResource_name(resource_id);
        viewDownloadDo.setResource_title(resource_name);
//        viewDownloadDo.setResource_id(req.getParameter("resource_id"));
//        viewDownloadDo.setResource_code(req.getParameter("resource_code"));
//        viewDownloadDo.setResource_name(req.getParameter("resource_name"));
//        viewDownloadDo.setResource_title(req.getParameter("resource_title"));
        viewDownloadDo.setUrl(req.getParameter("url"));
        viewDownloadDo.setCreate_time(RandomUtils.nowStr(""));
        /*插入下载日志*/
        AddFrequencyBo ee = new AddFrequencyBo();
        ee.setId(viewDownloadDo.getResource_id());
        ee.setTABLENAME(viewDownloadDo.getResource_code());
        viewDownloadDo.setHyfl_code(logService.getHyfl_codeByKnowledge(resource_code,resource_id));
        indexService.AddFrequency(ee);

        logMysqlMapper.insertDownLoadLog(viewDownloadDo);
    }

//    private void loginLog(HttpServletRequest req) throws IOException {

//这里获取不到登录信息
//        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//        Security_UserDetail detail = (Security_UserDetail) authentication.getPrincipal();
//        UserDo usr = detail.getUserDo();

//        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
//                new UsernamePasswordAuthenticationToken(userDo.getAccount(), userDo.getPassword());
//        /*查询数据库,验证账号密码*/
//        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
//        if (Objects.isNull(authenticate)) throw new RuntimeException("LoginServiceImpl");
//        /*获取用户信息*/
//        Security_UserDetail security_userDetail = (Security_UserDetail)authenticate.getPrincipal();
//        String user_account = security_userDetail.getUserDo().getAccount();
//        String user_name = security_userDetail.getUserDo().getUser_name();

//        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        HttpServletRequest request = requestAttributes.getRequest();
//
//        StringBuffer sb = new StringBuffer() ;
//        InputStream is = request.getInputStream();
//        InputStreamReader isr = new InputStreamReader(is);
//        BufferedReader br = new BufferedReader(isr);
//        String s = "" ;
//        while((s=br.readLine())!=null){
//            sb.append(s) ;
//        }
//        String result =sb.toString();
////        log.info("\n\n ----------- 请求 json 为 :"+result);
//
//        String account = req.getParameter("account");
//        System.out.println(account);
//
//
//    }

    private void searchLog(HttpServletRequest req) throws IOException {

        Map<String, Object> params = readFromBody(req);
        Object searchValue = params.get("searchValue");
        if(searchValue==null){
            return;
        }
        if (!StringUtils.hasLength(searchValue.toString())) {
            return;
        }

        SearchDo searchDo = new SearchDo();

        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            Security_UserDetail detail = (Security_UserDetail) authentication.getPrincipal();
            UserDo usr = detail.getUserDo();
            searchDo.setUser_id(usr.getAccount());
            searchDo.setUser_name(usr.getUser_name());
        } catch (Exception e) {
//            searchDo.setUser_id(usr.getAccount());
            searchDo.setUser_name("anonymous");
        }

        searchDo.setIp(req.getRemoteAddr());

        searchDo.setStr_query(params.get("searchValue").toString());

        searchDo.setCreate_time(RandomUtils.nowStr(""));
        Integer res = logMysqlMapper.insertSearchLog(searchDo);
        System.out.println("ooo");
    }

    public static Map<String, Object> getKeyAndValue(Object obj) {
        Map<String, Object> map = new HashMap<>();
        // 得到类对象
        Class userCla = (Class) obj.getClass();
        /* 得到类中的所有属性集合 */
        Field[] fs = userCla.getDeclaredFields();
        for (int i = 0; i < fs.length; i++) {
            Field f = fs[i];
            f.setAccessible(true); // 设置些属性是可以访问的
            Object val = new Object();
            try {
                val = f.get(obj);
                // 得到此属性的值
                map.put(f.getName(), val);// 设置键值
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }
        return map;
    }

    public Map<String, Object> readFromBody(HttpServletRequest req) {
        Map<String, Object> params = new HashMap<>();
        BufferedReader br = null;
        try {
            try {
                br = req.getReader();
            } catch (IOException e) {
                e.printStackTrace();
            }
            String str;
            StringBuilder wholeStr = new StringBuilder();
            while ((str = Objects.requireNonNull(br).readLine()) != null) {
                wholeStr.append(str);
            }
            if (StrUtil.isNotEmpty(wholeStr.toString())) {
                params = JSON.parseObject(wholeStr.toString(), Map.class);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return params;
    }
}
